package com.linshengjian.snowball.finance.service;

import com.linshengjian.snowball.core.BaseService;
import com.linshengjian.snowball.core.exception.BusinessException;
import com.linshengjian.snowball.core.exception.BusinessObjectNotFoundException;
import com.linshengjian.snowball.core.exception.SystemErrorException;
import com.linshengjian.snowball.core.page.PageData;
import com.linshengjian.snowball.core.page.PageParam;
import com.linshengjian.snowball.finance.UseType;
import com.linshengjian.snowball.finance.dao.SavingDao;
import com.linshengjian.snowball.finance.dao.SavingsRecordDao;
import com.linshengjian.snowball.finance.entity.SavingsEntity;
import com.linshengjian.snowball.finance.entity.SavingsRecordEntity;
import com.linshengjian.snowball.finance.model.Savings;
import com.linshengjian.snowball.finance.model.SavingsRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Service
public class SavingsServiceImpl implements ISavingsService {
    @Autowired
    private SavingDao savingDao;
    @Autowired
    private SavingsRecordDao recordDao;

    private String createOddNum() {
        return UUID.randomUUID().toString();
    }

    private SavingsEntity getSavings(Long savingId) throws BusinessObjectNotFoundException {
        SavingsEntity savingsEntity = savingDao.getOne(savingId);
        if (savingsEntity == null)
            throw new BusinessObjectNotFoundException("没有找到 SavingsEntity 对象：" + savingId);
        return savingsEntity;
    }

    @Override
    public Savings create() throws SystemErrorException {

        SavingsEntity entity = new SavingsEntity();

        entity = savingDao.save(entity);

        return entity.toModel();
    }

    @Override
    public Savings get(Long id) throws SystemErrorException {

        Optional<SavingsEntity> optional = savingDao.findById(id);
        if (optional.isPresent())
            return optional.get().toModel();

        return null;
    }

    @Override
    public PageData<SavingsRecord> list(Long savingsId, PageParam pageReq) throws SystemErrorException, BusinessException {
        PageRequest pageRequest = PageRequest.of(pageReq.getIndex() - 1, pageReq.getSize(), new Sort(Sort.Direction.DESC, "createTime"));
        Page<SavingsRecordEntity> page = recordDao.findBySavings_Id(savingsId, pageRequest);

        List<SavingsRecord> mList = new ArrayList<>();
        for (SavingsRecordEntity e : page.getContent()) {
            mList.add(e.toModel());
        }

        PageData<SavingsRecord> pageResp = new PageData<>();
        pageResp.setList(mList);
        pageResp.setIndex(page.getNumber() + 1);
        pageResp.setSize(page.getSize());
        pageResp.setTotalPage(page.getTotalPages());
        pageResp.setTotalRow(page.getTotalElements());
        return pageResp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SavingsRecord income(Long savingsId, Double amount, String remark) throws BusinessException, SystemErrorException {

        SavingsEntity savings = getSavings(savingsId);
        savings.setSurplus(BigDecimal.valueOf(savings.getSurplus()).add(BigDecimal.valueOf(amount)).doubleValue());
        savings.setIncome(BigDecimal.valueOf(savings.getIncome()).add(BigDecimal.valueOf(amount)).doubleValue());

        SavingsRecordEntity record = new SavingsRecordEntity();
        record.setOddNum(createOddNum());
        record.setType(UseType.income);
        record.setAmount(amount);
        record.setBalance(savings.getSurplus());
        record.setRemark(remark);
        record.setSavings(savings);

        record = recordDao.save(record);
        savingDao.save(savings);
        return record.toModel();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SavingsRecord expenditure(Long savingsId, Double amount, String remark) throws BusinessException, SystemErrorException{
        SavingsEntity savings = getSavings(savingsId);
        savings.setSurplus(BigDecimal.valueOf(savings.getSurplus()).subtract(BigDecimal.valueOf(amount)).doubleValue());
        savings.setExpenditure(BigDecimal.valueOf(savings.getExpenditure()).add(BigDecimal.valueOf(amount)).doubleValue());

        SavingsRecordEntity record = new SavingsRecordEntity();
        record.setOddNum(createOddNum());
        record.setType(UseType.expenditure);
        record.setAmount(amount);
        record.setBalance(savings.getSurplus());
        record.setRemark(remark);
        record.setSavings(savings);

        record = recordDao.save(record);
        savingDao.save(savings);

        return record.toModel();
    }
}
